package middleware

import (
	"encoding/gob"
	"fmt"
	"github.com/gin-contrib/sessions"
	"github.com/gin-gonic/gin"
	"net/http"
	"time"
)

type LoginMiddlewareBuilder struct {
}

func (m *LoginMiddlewareBuilder) CheckLogin() gin.HandlerFunc {
	// 注册一下这个类型
	gob.Register(time.Now()) // 使刷新redis 过期时间可以序列化 存字节切片  到redis   time.Now() 类型
	return func(ctx *gin.Context) {
		path := ctx.Request.URL.Path
		if path == "/users/login_session" {
			// 不需要登录校验
			return
		}
		sess := sessions.Default(ctx)
		userId := sess.Get("userId") //  服务于 固定时间刷新
		if sess.Get("userId") == nil {
			// 中断，不要往后执行，也就是不要执行后面的业务逻辑
			ctx.AbortWithStatus(http.StatusUnauthorized)
			fmt.Println("登陆校验失败")
			return
		}

		// 固定间隔刷新 每分钟刷新一次
		now := time.Now()
		const updateTimeKey = "update_time" //第一次访问的时候 设置  updateTimeKey
		// 试着拿出上一次刷新时间
		val := sess.Get(updateTimeKey)
		lastUpdateTime, ok := val.(time.Time) // 上一次的更新时间  类型断言  断言是一个时间类型

		if val == nil || !ok || now.Sub(lastUpdateTime) > time.Second*10 {
			// val==nil 第一次登陆
			// !ok 类型断言失败了
			// now.Sub(lastUpdateTime) > time.Second*10 间隔大于10秒  测试时 设置每隔十秒就刷新    第一次的过期时间时30秒
			sess.Set(updateTimeKey, now) // 把时间放进去
			sess.Set("userId", userId)   //  gin session 中的数据是覆盖的 需要重写
			sess.Options(sessions.Options{
				MaxAge: 30, //  同时 控制 redis 时的  数据过期时期 30秒过期
			})
			err := sess.Save() //
			if err != nil {
				// 打日志
				fmt.Println(err)
			}
		}
	}
}
